#! /usr/bin/env python
from simpleOSC import *
from visual import *
import math
import argparse

# Dummy Screen
# This program will provide a dummy screen for data visualization, which will be controlled by OSC messages.
# When it begins executing, the only message that it will respond to is '/create'.
# Data for that message should be a string containing the name of the message related to another object, as:
# sendOSCMsg("/create", ["/someObject"]) 
# (list form is important!)
#
# After that, every time the server receives the message "/someObject" it will update its properties to the
# data sent in the message. 
# This data should be a list of 6 numbers:
# x and y positions of the object - 0 to 1, where 1 is the full width or height of the canvas
# z position, which is the size of the object - 0 to 1, where 1 is the full width or height of the canvas
# r, g, b color descriptors of the object (or just set them to 0, 0, 0 if you want it all black)
# which means something like this:
# sendOSCMsg("/someObject", [.7, .2, .1, 0, 1, 1])
#
# Code written by Tiago F. Tavares
#
# Maybe I will add some more stuff, if I fell like...
# 
# You can use this both as a library and as a standalone application.

#GlobalWidget = None; # It's ugly to use global variables. Doesn't matter, I do a lot of ugly stuff...

# Create a GTK+ widget on which we will draw using Cairo
class Screen():
	Events = {};
	Spheres = {};
	lastEvent = None;
	scene = None;

	def __init__(self):
		self.scene = display(title='GhostHands 3D', x=0, y=0, width=800, height=600, center=(0.5,0.5,0), background=(0,0,0), range=(1.5,1.5,5), autoscale=False)
		wallR = box(pos=(0,0,-1), size=(1,1,0.2), color=color.white)
		wallR2 = box(pos=(1,1,-1), size=(1,1,0.2), color=color.gray(2))

	def setEvent(self, address, data, update=1):
#		print "Setting event ", address, " to ", data
		if address in self.Events:
			self.Events[address] = data;
			self.Spheres[address].pos = vector(data[0], data[1], data[2]);
			self.Spheres[address].color = vector(data[3], data[4], data[5]);		
		else:
			self.Events[address] = data
			self.Spheres[address] = sphere(pos = (data[0], data[1], data[2]), radius = 0.05, color = (data[3], data[4], data[5]));


	def getData(self, address):
		return self.Events[address];


def newObject(addr, tags, data, source):
	setOSCHandler(data[0], setEvent)
	print "Added OSC handler for object: ", data[0]
	reportOSCHandlers()

def setEvent(addr, tags, data, source, etc=0):
	GlobalWidget.setEvent(addr, data)

def start(Widget, IP=None, port=None): # Deprecated and is only here for compatibility reasons
	global GlobalWidget
	GlobalWidget = Screen()
	return GlobalWidget

def run(Widget, IP=None, port=None):
	try:
		if IP != None:
			initOSCServer(IP, port, 1)
			setOSCHandler("/create", newObject)
			reportOSCHandlers()
			print "Server up and running!"
			print "Using interface: ", IP, " on port ", port

		while(1):
			pass;

	except KeyboardInterrupt:
		pass;

	if IP != None:
		print "\nClosing OSCServer."
		print "Waiting for Server-thread to finish"
		closeOSC()

	print "Done"

if __name__ == "__main__":
	global GlobalWidget

	parser = argparse.ArgumentParser(description='Visual 3D based, OSC-controlled data display device')
	parser.add_argument('--IP', '-i', metavar='IP', default='127.0.0.1', type=str, help='IP interface to use (default: 127.0.0.1)')
	parser.add_argument('--Port', '-p', metavar='Port', default=9001, type=int, help='Port to be used (default: 9001)') # Our default is OVER 9000!
	args = parser.parse_args()
	print "Trying to open server using interface ", args.IP, " on port ", args.Port

#	start(Screen, args.IP, args.Port)
	run(Screen, args.IP, args.Port)

